/*
 * SPDX-FileCopyrightText: 2022-2023 liulinsong <liulinsong@kylinos.cn>
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 *
 */

#include "devicestatusmanager.h"
#include "fcitx/addonfactory.h"
#include "physicalkeyboardwatcherstrategy.h"
#include "tabletmodewatcherstrategy.h"

namespace fcitx {

DeviceStatusManager::DeviceStatusManager(Instance *instance)
    : instance_(instance),
      physicalKeyboardWatcher_(createPhysicalKeyboardWatcherStrategy(),
                               instance),
      tabletModeWatcher_(createTabletModeWatcherStrategy(), instance) {}

DeviceStatusManager::~DeviceStatusManager() = default;

std::unique_ptr<StatusManagerWatcher::Strategy>
DeviceStatusManager::createPhysicalKeyboardWatcherStrategy() {
    auto physicalKeyboardAvailabilityChangedCallback = [this]() {
        const bool isPhysicalKeyboardAvailable =
            physicalKeyboardWatcher_.isSubjectAvailable();
        if (isPhysicalKeyboardAvailable) {
            instance_->setInputMethodMode(InputMethodMode::PhysicalKeyboard);
        } else {
            instance_->setInputMethodMode(InputMethodMode::OnScreenKeyboard);
        }

        instance_->setVirtualKeyboardAutoShow(!isPhysicalKeyboardAvailable);

        updateVirtualKeyboardAutoHide();
    };

    return std::unique_ptr<StatusManagerWatcher::Strategy>(
        new PhysicalKeyboardWatcherStrategy(
            std::move(physicalKeyboardAvailabilityChangedCallback)));
}

std::unique_ptr<StatusManagerWatcher::Strategy>
DeviceStatusManager::createTabletModeWatcherStrategy() {
    auto tabletModeAvailabilityChangedCallback = [this]() {
        updateVirtualKeyboardAutoHide();
    };

    return std::unique_ptr<StatusManagerWatcher::Strategy>(
        new TabletModeWatcherStrategy(
            std::move(tabletModeAvailabilityChangedCallback)));
}

bool DeviceStatusManager::shouldVirtualKeyboardAutoHide() const {
    const bool isTabletModeAvailable = tabletModeWatcher_.isSubjectAvailable();
    if (isTabletModeAvailable) {
        return true;
    }

    const bool isPhysicalKeyboardUnavailable =
        !physicalKeyboardWatcher_.isSubjectAvailable();

    return isPhysicalKeyboardUnavailable;
}

void DeviceStatusManager::updateVirtualKeyboardAutoHide() {
    instance_->setVirtualKeyboardAutoHide(shouldVirtualKeyboardAutoHide());
}

class DeviceStatusManagerFactory : public AddonFactory {
    AddonInstance *create(AddonManager *manager) override {
        return new DeviceStatusManager(manager->instance());
    }
};

} // namespace fcitx

FCITX_ADDON_FACTORY(fcitx::DeviceStatusManagerFactory)
